home *** CD-ROM | disk | FTP | other *** search
- /****************************************************************************
- *
- * OSLClassGraphicObject.c
- *
- * OSL support for the cGraphicObject Apple Event Registry object
- *
- ****************************************************************************/
-
- #include <stdio.h> // for sprintf()
- #include <string.h> // for strlen()
- #include <Errors.h>
-
- #include "OSLClassGraphicObject.h"
- #include "OSLClassDocument.h"
- #include "AERCoreSuite.h"
- #include "AppleEvent.h"
-
- #include "Documents.h"
- #include "DocumentADT.h"
- #include "DocumentHelpers.h"
-
-
- #include "ElementADT.h"
- #include "ElementHelpers.h"
-
- #include "Assertion.h"
-
- #include "StringUtils.h"
-
- #include "OSLHelpers.h"
-
- #include "Imaging.h"
-
- // ----------------------------------------------------------------------------
- // Core Suite Object Event handlers
- // ----------------------------------------------------------------------------
-
- static OSErr HandleCount (AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply, long refcon);
- static OSErr HandleDataSize (AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply, long refcon);
- static OSErr HandleDelete (AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply, long refcon);
- static OSErr HandleDuplicate (AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply, long refcon);
- static OSErr HandleExists (AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply, long refcon);
- static OSErr HandleGetData (AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply, long refcon);
- static OSErr HandleMake (AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply, long refcon);
- static OSErr HandleMove (AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply, long refcon);
- static OSErr HandleSetData (AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply, long refcon);
-
- // ----------------------------------------------------------------------------
- // Object Accessor functions
- // ----------------------------------------------------------------------------
-
- static OSErr
- MakeNewObject(
- const DescType objectToCreate,
- const DescType insertionPosition,
- const AEDesc *token,
- const AEDesc *ptrToWithData,
- const AEDesc *ptrToWithProperties,
- AppleEvent *reply);
-
-
- static OSErr
- PropertyFromListAccessor(
- DescType desiredClass,
- const AEDesc* containerToken,
- DescType containerClass,
- DescType keyForm,
- const AEDesc* keyData,
- AEDesc* resultToken,
- long refcon);
-
- static OSErr
- PropertyFromObjectAccessor(
- DescType desiredClass,
- const AEDesc* containerToken,
- DescType containerClass,
- DescType keyForm,
- const AEDesc* keyData,
- AEDesc* resultToken,
- long refcon);
-
- static OSErr GetDataFromList (AEDesc *srcList, AEDesc *desiredTypes, AEDesc *dstList);
- static OSErr GetDataFromObject (AEDesc *token, AEDesc *desiredTypes, AEDesc *data);
-
- static OSErr SetDataForList (AEDesc *token, AEDesc *data);
- static OSErr SetDataForObject (AEDesc *token, AEDesc *data);
-
- static Boolean CanGetProperty (DescType class, DescType property);
- static Boolean CanSetProperty (DescType class, DescType property);
- static OSErr SetProperties (DocumentReference document, ElementReference element, AEDesc *propertyRecord);
-
- // ----------------------------------------------------------------------------
- // ----- cGraphicObject - accessors for everything graphical
- // ----------------------------------------------------------------------------
-
- static pascal OSErr
- GraphicObjectFromDocumentAccessor(DescType desiredClass,
- const AEDesc* containerToken,
- DescType containerClass, // cDocument
- DescType keyForm,
- const AEDesc* keyData,
- AEDesc* resultToken,
- long refcon);
-
- static pascal OSErr
- GraphicObjectFromGroupAccessor (DescType desiredClass,
- const AEDesc* containerToken,
- DescType containerClass, // cGroupedGraphic
- DescType keyForm,
- const AEDesc* keyData,
- AEDesc* resultToken,
- long refcon);
-
-
- static pascal OSErr
- GraphicObjectAccessor( ElementList list,
- DescType desiredClass, // any subclass of cGraphicObject
- const AEDesc* containerToken,
- DescType containerClass,
- DescType keyForm,
- const AEDesc* keyData,
- AEDesc* resultToken, // specified object is returned in result
- long refcon );
-
- // ----------------------------------------------------------------------------
- // Application-specific helpers
- // ----------------------------------------------------------------------------
-
- static OSErr DoMove (AEDesc *token, DescType insertionPos, AEDesc *toToken);
-
- static OSErr MakePolygonFromAEPointList (DocumentReference document, ElementReference element, AEDescList* list);
- static OSErr MakeGroupFromAEList (DocumentReference document, ElementReference element, AEDescList* list);
-
- static OSErr ProcessFormRelativePostition (const AEDesc* containerToken, const AEDesc *keyData, DescType desiredClass, ElementReference *element);
-
- static PolyHandle CreatePolygonFromPoints (short numberOfPoints, Point *pointList);
- static short CountPolygonPoints (PolyHandle polygon);
- static Point GetPolygonPoint (PolyHandle polygon, short pointIndex);
-
- /*****************************************************************************
- *
- * GraphicObjectEventDispatcher
- *
- * Handles AppleEvents for graphic objects
- *
- *****************************************************************************/
-
- OSErr
- GraphicObjectEventDispatcher(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply, long refcon)
- {
- OSErr error = noErr;
-
- AEEventID eventID;
- OSType typeCode;
- Size actualSize = 0L;
-
- // Get the event ID
-
- error = AEGetAttributePtr(appleEvent,
- keyEventIDAttr,
- typeType,
- &typeCode,
- (Ptr)&eventID,
- sizeof(eventID),
- &actualSize);
- if (error != noErr) {
- return error;
- }
-
- switch (eventID)
- {
- case kAEClone:
- error = HandleDuplicate(token, appleEvent, reply, refcon);
- break;
-
- case kAECountElements:
- error = HandleCount(token, appleEvent, reply, refcon);
- break;
-
- case kAECreateElement:
- error = HandleMake(token, appleEvent, reply, refcon);
- break;
-
- case kAEDelete:
- error = HandleDelete(token, appleEvent, reply, refcon);
- break;
-
- case kAEDoObjectsExist:
- error = HandleExists(token, appleEvent, reply, refcon);
- break;
-
- case kAEGetData:
- error = HandleGetData(token, appleEvent, reply, refcon);
- break;
-
- case kAEGetDataSize:
- error = HandleDataSize(token, appleEvent, reply, refcon);
- break;
-
- case kAEMove:
- error = HandleMove(token, appleEvent, reply, refcon);
- break;
-
- case kAESetData:
- error = HandleSetData(token, appleEvent, reply, refcon);
- break;
-
- default:
- error = errAEEventNotHandled;
- break;
- }
-
- if (error != noErr && reply != NULL && reply->descriptorType != typeNull)
- PutReplyErrorNumber(reply, error);
-
- return error;
- }
-
- #pragma mark -
- // ----------------------------------------------------------------------------
- // Core Suite Object Event handlers
- // ----------------------------------------------------------------------------
- // This function counts anything that can be contained inside of a Graphic Object
- // It currently just counts things inside a grouped graphic object.
-
- static OSErr
- HandleCount(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply, long refcon)
- {
- #pragma unused (refcon)
-
- OSErr error = noErr;
- long numberOfObjects = 0L;
- DescType objectClass = 0L;
-
- DocumentReference document = nil;
- ElementReference element = nil;
- ElementType elementType;
-
- // Get the class of object that we will count
-
- error = GetObjectClassFromAppleEvent(appleEvent, &objectClass);
- if (error)
- goto CleanUp;
-
- // Make sure we got & handled all of the required parameters
-
- error = CheckForUnusedParameters(appleEvent);
- if (error)
- goto CleanUp;
-
- // a token list could be sent to this handler by a formWhose resolution,
- // such as "count rectangles whose width > 100"
-
- if (token->descriptorType == typeAEList)
- {
- AEDescList flatList = {typeNull, nil};
-
- error = AECreateList(NULL, 0L, false, &flatList);
- if (error == noErr)
- error = FlattenAEList(token, &flatList);
-
- if (error == noErr)
- error = AECountItems(token, &numberOfObjects);
-
- if (error == noErr)
- error = AEPutParamPtr(reply, keyAEResult, typeLongInteger, (Ptr)&numberOfObjects, sizeof(long));
-
- AEDisposeDesc(&flatList);
-
- goto CleanUp;
- }
-
- error = GetDocumentReferenceFromToken(token, &document);
- if (error != noErr)
- goto CleanUp;
-
- error = GetElementReferenceFromToken(token, &element);
- if (error != noErr)
- goto CleanUp;
-
- elementType = GetElementType(element);
-
- if (elementType == kGroup)
- {
- if (error == noErr)
- numberOfObjects = CountElementsByClass(GetSubElementList(element), objectClass);
- }
- else
- {
- error = errAECantHandleClass;
- }
-
- // Now return the result in the reply apple event
-
- if (error == noErr && reply->descriptorType != typeNull)
- error = AEPutParamPtr(reply, keyAEResult, typeLongInteger, (Ptr)&numberOfObjects, sizeof(long));
-
- CleanUp:
-
- return error;
- }
-
- // ----------------------------------------------------------------------------
- // Just get the data in a handle and return its handle size
-
- static OSErr
- HandleDataSize(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply, long refcon)
- {
- OSErr error = noErr;
- AEDesc data = {typeNull, nil};
- long size = 0L;
-
- // First, get the data
- error = HandleGetData(token, appleEvent, reply, refcon);
-
- // now, extract it from the reply
-
- if (error == noErr)
- error = AEGetKeyDesc(reply,
- keyDirectObject,
- typeWildCard,
- &data);
-
- if (error == noErr)
- {
- if (data.dataHandle != nil)
- {
- size = GetHandleSize(data.dataHandle);
- }
- error = AEPutParamPtr(reply,
- keyAEResult,
- typeLongInteger,
- (Ptr)&size,
- sizeof(long));
- }
-
- AEDisposeDesc(&data);
-
- return error;
-
- }
-
- // ----------------------------------------------------------------------------
- // Delete a Graphic Object
-
- static OSErr HandleDelete(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply, long refcon)
- {
- #pragma unused (reply, refcon)
-
- OSErr error = noErr;
-
- DocumentReference document = nil;
- ElementReference element = nil;
-
- // Make sure we got & handled all of the required parameters
-
- error = CheckForUnusedParameters(appleEvent);
- if (error)
- goto CleanUp;
-
- if (token->descriptorType == typeAEList)
- {
- long index;
- long numItems;
- AEKeyword keyword;
- AEDesc item;
-
- AEDescList flatList = {typeNull, nil};
-
- error = AECreateList(NULL, 0L, false, &flatList);
- if (error == noErr)
- error = FlattenAEList(token, &flatList);
-
- if (error == noErr)
- {
- error = AECountItems(token, &numItems);
-
- for (index = numItems; index >= 1; index--)
- {
- error = AEGetNthDesc(&flatList, index, typeWildCard, &keyword, &item);
-
- if (error == noErr)
- error = GetDocumentReferenceFromToken(&item, &document);
-
- if (error == noErr)
- error = GetElementReferenceFromToken(&item, &element);
-
- if (error == noErr)
- {
- IMDelete(document, element);
- MarkDocumentAsChanged(document);
- }
-
- AEDisposeDesc(&item);
- }
- }
- AEDisposeDesc(&flatList);
- }
- else
- {
- error = GetDocumentReferenceFromToken(token, &document);
-
- if (error == noErr)
- error = GetElementReferenceFromToken(token, &element);
-
- if (error == noErr)
- {
- IMDelete(document, element);
- MarkDocumentAsChanged(document); // and the document has now been modified!
- }
- }
- CleanUp:
-
- return error;
- }
-
- // ----------------------------------------------------------------------------
- // receives messages like "duplicate rectangle 1 of document 1" messages
-
- static OSErr
- HandleDuplicate(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply, long refcon)
- {
- #pragma unused (refcon)
-
- OSErr error = noErr;
-
- DocumentReference document = nil;
-
- ElementReference oldElement = nil;
- ElementReference newElement = nil;
- ElementReference insElement = nil;
-
- OSType typeCode;
- Size actualSize;
-
- DescType insertionPos = typeNull;
- AEDesc insertionLoc = {typeNull, nil};
- AEDesc objectSpec = {typeNull, nil};
- AEDesc insertionToken = {typeNull, nil};
-
- error = GetDocumentReferenceFromToken(token, &document);
-
- if (error == noErr)
- error = GetElementReferenceFromToken(token, &oldElement);
-
- // For Duplicate, there is an OPTIONAL typeInsertionLoc record
- // which will be there when the script contains something like
- // "duplicate oval 1 to after rectangle 3". If this parameter is found,
- // we coerce the insertionLoc record into an AERecord so we can extract the fields.
- // Notice that this is a OPTIONAL parameter, so we give it a default behavior
- // by duplicating to after the source element.
-
- error = AEGetParamDesc(appleEvent, // Extract as a AERecord
- keyAEInsertHere,
- typeAERecord,
- &insertionLoc);
-
- if (error == errAEDescNotFound)
- {
- insertionPos = kAEBeginning;
- error = noErr;
- }
- else if (error == noErr)
- {
-
- // Get the enumerated insertion location (at end, in front, before, after, replace.)
-
- error = AEGetKeyPtr(&insertionLoc,
- keyAEPosition, // insertion location
- typeEnumeration,
- &typeCode,
- (Ptr)&insertionPos,
- sizeof(insertionPos),
- &actualSize);
-
- // Extract and resolve the object specifier from the insertion location record.
- // In a case like "make new rectangle before rectangle 1 of document 1",
- // the ospec will resolve to "rectangle 1 of document 1"
-
- error = AEGetKeyDesc(&insertionLoc,
- keyAEObject,
- typeWildCard,
- &objectSpec);
- }
-
- // if there was a object specifier in the insertion location (eg, "before rectangle 1 of document 1",
- // then we call AEResolve() to get a token for it,
- // Otherwise, is was something like "at end" or "at beginning", which is also OK,
- // then deal with it correctly later.
-
- if (objectSpec.descriptorType != typeNull)
- {
- error = AEResolve(&objectSpec,
- kAEIDoMinimum,
- &insertionToken);
-
- if (error == noErr)
- {
- error = GetElementReferenceFromToken(&insertionToken, &insElement);
- }
- else
- {
- goto CleanUp;
- }
- }
-
- // ----------- create the new element ------------------
-
- if (error == noErr)
- {
- newElement = CloneElement(oldElement);
- error = ElementError();
-
- if (newElement != nil && error == noErr)
- {
- if (insElement == nil)
- {
- AdoptOrphanInsertingBeforeElement(newElement, oldElement); // visually, behind the source element
- }
- else
- {
- switch (insertionPos)
- {
- case kAEBeginning:
- // add new element to end of the list
- AdoptOrphan(GetDocumentElementList(document), newElement);
- break;
-
- case kAEEnd:
- // add new element to the beginning of the list
- insElement = GetFirstElement(GetDocumentElementList(document));
- if (insElement != nil)
- {
- AdoptOrphanInsertingBeforeElement(newElement, insElement);
- }
- break;
-
- case kAEBefore:
- AdoptOrphanInsertingAfterElement(newElement, insElement);
- break;
-
- case kAEAfter:
- AdoptOrphanInsertingBeforeElement(newElement, insElement);
- break;
-
- case kAEReplace:
- AdoptOrphanInsertingAfterElement(newElement, insElement);
- DestroyElement(insElement);
- break;
-
- default:
- SysBeep(2);
- break;
- }
- }
-
- IMDraw(document);
- MarkDocumentAsChanged(document);
- }
- }
-
- // return a reference to the new graphic object in the AppleEvent reply parameter
-
- if (error == noErr && reply != NULL && document != nil && newElement != nil)
- {
- AEDesc ospec = {typeNull, nil};
-
- error = CreateGraphicObjectOSpec(document, newElement, &ospec);
-
- if (error == noErr)
- {
- AEPutParamDesc(reply, keyDirectObject, &ospec);
- }
-
- AEDisposeDesc(&ospec);
- }
-
- CleanUp:
-
- AEDisposeDesc(&insertionLoc);
- AEDisposeDesc(&insertionToken);
- AEDisposeDesc(&objectSpec);
-
- return error;
- }
-
- // ----------------------------------------------------------------------------
- // "If <rectangle 1 of document 1> exists..."
- // The AEResolve() function in AERCoreSuite.c will already have filtered
- // out all cases where the object did not exist, so this function should
- // always return TRUE.
-
- static OSErr
- HandleExists(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply, long refcon)
- {
- #pragma unused (token, appleEvent, refcon)
-
- OSErr error = noErr;
- Boolean foundIt = true;
-
- error = AEPutParamPtr(reply,
- keyAEResult,
- typeBoolean,
- (Ptr)&foundIt,
- sizeof(Boolean));
-
- return error;
- }
-
- // ----------------------------------------------------------------------------
-
- static OSErr
- HandleGetData(AEDesc *tokenOrTokenList, const AppleEvent *appleEvent, AppleEvent *reply, long refcon)
- {
- #pragma unused (refcon)
-
- OSErr error = noErr;
- AEDesc data = {typeNull, nil};
- AEDesc desiredTypes = {typeNull, nil};
-
- AEGetParamDesc(appleEvent, keyAERequestedType, typeAEList, &desiredTypes);
-
- error = GetDataFromGraphicObject(tokenOrTokenList, &desiredTypes, &data);
-
- if (error == noErr && reply->descriptorType != typeNull)
- error = AEPutKeyDesc(reply, keyDirectObject, &data); // return the requested data in the reply
-
- AEDisposeDesc(&data);
- AEDisposeDesc(&desiredTypes);
-
- return error;
- }
-
- // ----------------------------------------------------------------------------
- // On entry, the token is a simple AEDesc that just contains the type of object
- // we are expected to create. We also extract properties and data, which can be
- // used to initialize the new object. In addition, there is an insertion location
- // telling us where to insert the new element.
-
- static OSErr
- HandleMake(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply, long refcon)
- {
- #pragma unused (refcon)
-
- OSErr error = noErr;
-
- OSType typeCode;
- Size actualSize;
-
- DescType newObjClass = typeNull;
- DescType insertionPos = typeNull;
-
- AEDesc insertionLoc = {typeNull, nil};
- AEDesc objectSpec = {typeNull, nil};
-
- long documentNumber = 0L;
- unsigned long elementNumber = 0L;
-
- DocumentReference document = nil;
- ElementReference newElement = nil;
- ElementReference oldElement = nil;
-
- // Optional parameters
- AEDesc withData = {typeNull, nil};
- AEDesc withProperties = {typeNull, nil};
-
- AEDesc *ptrToWithData = NULL;
- AEDesc *ptrToWithProperties = NULL;
-
- newObjClass = **(DescType**)(token->dataHandle); // This is the class of object we should create
-
- // For Create Element, the object specifier is contained in
- // a typeInsertionLoc record instead of in a direct parameter.
- // We coerce the insertionLoc record into an AERecord so we can extract the fields.
- // Notice that this is a REQUIRED parameter, but we give it a default behavior
- // by creating a new element at beginning of the first document
-
- error = AEGetParamDesc(appleEvent, // Extract as a AERecord
- keyAEInsertHere,
- typeAERecord,
- &insertionLoc);
-
- if (error == errAEDescNotFound)
- {
- insertionPos = kAEBeginning;
- error = noErr;
- }
- else if (error == noErr)
- {
-
- // Get the enumerated insertion location (at end, in front, before, after, replace.)
-
- error = AEGetKeyPtr(&insertionLoc,
- keyAEPosition, // insertion location
- typeEnumeration,
- &typeCode,
- (Ptr)&insertionPos,
- sizeof(insertionPos),
- &actualSize);
-
- // Extract and resolve the object specifier from the insertion location record.
- // In a case like "make new rectangle before rectangle 1 of document 1",
- // the ospec will resolve to "rectangle 1 of document 1"
-
- error = AEGetKeyDesc(&insertionLoc,
- keyAEObject,
- typeWildCard,
- &objectSpec);
-
- }
-
- // if there was a object specifier in the insertion location (eg, "before rectangle 1 of document 1",
- // then we call AEResolve() to get a token for it,
- // Otherwise, is was something like "at end" or "at beginning", which is also OK,
- // then deal with it correctly later.
-
- if (objectSpec.descriptorType == typeNull)
- {
- AEDisposeDesc(token); // destroy it's old representation, token will now be null descriptor
- }
- else
- {
- error = AEResolve(&objectSpec,
- kAEIDoMinimum,
- token); // token will contain info about the object to insert before, after, etc.
-
- if (error != noErr)
- {
- goto CleanUp;
- }
- }
-
- switch (newObjClass)
- {
- case cOval: // Sketch can make these graphic objects
- case cPolygon:
- case cRectangle:
- case cRoundedRectangle:
- case cGraphicLine:
- case cGroupedGraphic:
- error = noErr;
- break;
-
- default:
- error = errAEEventNotHandled;
- break;
- }
-
- // Extract the optional parameters from the AppleEvent
-
- // ----- [with data ....] -----
-
- error = AEGetParamDesc(appleEvent,
- keyAEData,
- typeWildCard,
- &withData);
-
- if (error != noErr && error != errAEDescNotFound)
- goto CleanUp;
-
- if (error == errAEDescNotFound)
- error = noErr;
- else
- ptrToWithData = &withData;
-
- // ----- [with properties {property: value, ...}] -----
-
- error = AEGetParamDesc(appleEvent,
- keyAEPropData,
- typeWildCard,
- &withProperties);
-
- if (error != noErr && error != errAEDescNotFound)
- goto CleanUp;
-
- if (error == errAEDescNotFound)
- error = noErr;
- else
- ptrToWithProperties = &withProperties;
-
- // Finally, use the token and other parameters to create & initialize the object
-
- if (error == noErr)
- error = MakeNewObject(newObjClass, insertionPos, token, ptrToWithData, ptrToWithProperties, reply);
-
- CleanUp:
-
- AEDisposeDesc(&insertionLoc);
- AEDisposeDesc(&objectSpec);
- AEDisposeDesc(&withData);
- AEDisposeDesc(&withProperties);
-
- return error;
- }
-
- // ----------------------------------------------------------------------------
- // Move a graphic object: On entry, the token parameter contains the resolution
- // of the object we want to move. The direct parameter is a object specifier for
-
- static OSErr
- HandleMove(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply, long refcon)
- {
- #pragma unused (refcon)
-
- OSErr error = noErr;
-
- OSType typeCode;
- Size actualSize;
-
- DescType insertionPos = kAEBeginning;
-
- AEDesc objectSpec = {typeNull, nil};
- AEDesc result = {typeNull, nil};
- AEDesc insertionLoc = {typeNull, nil};
- AEDesc toToken = {typeNull, nil};
-
- // The insertion location is an object specifier that results from an
- // expression such as "to behind rectangle 3"
- // Now is the time to parse it
-
- error = AEGetParamDesc(appleEvent, // Extract insertion location as a AERecord
- keyAEInsertHere,
- typeAERecord,
- &insertionLoc);
-
- if (error == errAEDescNotFound)
- {
- insertionPos = kAEBeginning;
- error = noErr;
- }
- else if (error == noErr)
- {
-
- // Get the enumerated insertion location (at end, in front, before, after, replace.)
-
- error = AEGetKeyPtr(&insertionLoc,
- keyAEPosition, // insertion location
- typeEnumeration,
- &typeCode,
- (Ptr)&insertionPos,
- sizeof(insertionPos),
- &actualSize);
-
- // Extract and resolve the object specifier from the insertion location record.
- // In a case like "move oval 1 to before rectangle 1 of document 1",
- // the ospec will resolve to "rectangle 1 of document 1"
-
- error = AEGetKeyDesc(&insertionLoc,
- keyAEObject,
- typeWildCard,
- &objectSpec);
- }
-
- // if there was a object specifier in the insertion location (eg, "before rectangle 1 of document 1",
- // then we call AEResolve() to get a token for it,
- // Otherwise, is was something like "at end" or "at beginning", which is also OK,
- // then deal with it correctly later.
-
- if (objectSpec.descriptorType != typeNull)
- {
- error = AEResolve(&objectSpec,
- kAEIDoMinimum,
- &toToken); // token will contain info about the object to move before, after, etc.
-
- if (error != noErr)
- {
- goto CleanUp;
- }
- }
-
- // Make sure we got & handled all of the required parameters
-
- error = CheckForUnusedParameters(appleEvent);
- if (error)
- goto CleanUp;
-
- // Do the application-specific part of the job
-
- error = DoMove(token, insertionPos, &toToken);
- if (error != noErr)
- goto CleanUp;
-
- // Return, in the AppleEvent reply, a reference to the object that was moved
-
- if (reply->dataHandle)
- {
- AEDesc ospec = {typeNull, nil};
- DocumentReference document = nil;
- ElementReference element = nil;
-
- GetDocumentReferenceFromToken(token, &document);
- GetElementReferenceFromToken(token, &element);
-
- error = CreateGraphicObjectOSpec(document, element, &ospec);
-
- if (error == noErr)
- {
- AEPutParamDesc(reply, keyDirectObject, &ospec);
- }
-
- AEDisposeDesc(&ospec);
- }
-
- CleanUp:
- AEDisposeDesc(&objectSpec);
- AEDisposeDesc(&insertionLoc);
- AEDisposeDesc(&toToken);
-
- return error;
- }
-
- // ----------------------------------------------------------------------------
- // Set data basically passes responsibility to WriteToken() below. However,
- // one important task here is to filter out properties that are read-only.
-
- static OSErr
- HandleSetData(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply, long refcon)
- {
- #pragma unused (reply, refcon)
-
- OSErr error = noErr;
- AEDesc data = {typeNull, nil};
-
- DescType propertyCode;
- DescType objectClass;
-
- switch (token->descriptorType)
- {
- case typeAEList:
- error = ExtractKeyDataParameter(appleEvent, &data);
- if (error == noErr)
- error = SetDataForList(token, &data);
- break;
-
- case cProperty:
- propertyCode = ExtractPropertyCodeFromToken(token);
- objectClass = ExtractObjectClassFromToken(token);
- if (CanSetProperty(objectClass, propertyCode))
- {
- error = ExtractKeyDataParameter(appleEvent, &data);
-
- if (error == noErr)
- error = SetDataForObject(token, &data);
- }
- else
- {
- error = errAENotModifiable;
- }
- break;
-
- default:
- error = errAENotModifiable;
- break;
- }
-
- AEDisposeDesc(&data);
-
- return error;
- }
-
- #pragma mark -
- // -----------------------------------------------------------------------------
- // Object Accessors
- //------------------------------------------------------------------------------
- // NOTE: each supported object has 4 accessors installed:
- // object-from-document : handles "oval 1 of document 2"
- // object-from-group : handles "oval 1 of graphic group 2"
- // object-from-anything : handles "oval before rectangle 1"
- // property-from-object : handles "fill color of oval 1"
-
- OSErr
- InstallGraphicObjectAccessors(void)
- {
-
- OSErr error;
-
- // ----- Graphic Object - a generic handler for all subclasses of cGraphicObject
-
- error = AEInstallObjectAccessor(cGraphicObject,
- cDocument,
- NewOSLAccessorProc(GraphicObjectFromDocumentAccessor),
- 0L,
- false);
-
- if (error == noErr)
- error = AEInstallObjectAccessor(cGraphicObject,
- typeWildCard, // for formRelativePosition
- NewOSLAccessorProc(GraphicObjectFromDocumentAccessor),
- 0L,
- false);
-
- if (error == noErr)
- error = AEInstallObjectAccessor(cGraphicObject,
- cGroupedGraphic,
- NewOSLAccessorProc(GraphicObjectFromGroupAccessor),
- 0L,
- false);
- if (error == noErr)
- error = AEInstallObjectAccessor(cProperty,
- cGraphicObject,
- NewOSLAccessorProc(PropertyFromGraphicObjectAccessor),
- 0L,
- false);
- // ----- OVAL
-
- if (error == noErr)
- error = AEInstallObjectAccessor(cOval,
- cDocument,
- NewOSLAccessorProc(GraphicObjectFromDocumentAccessor),
- 0L,
- false);
- if (error == noErr)
- error = AEInstallObjectAccessor(cOval,
- typeWildCard, // for formRelativePosition
- NewOSLAccessorProc(GraphicObjectFromDocumentAccessor),
- 0L,
- false);
-
- if (error == noErr)
- error = AEInstallObjectAccessor(cOval,
- cGroupedGraphic,
- NewOSLAccessorProc(GraphicObjectFromGroupAccessor),
- 0L,
- false);
-
- if (error == noErr)
- error = AEInstallObjectAccessor(cProperty,
- cOval,
- NewOSLAccessorProc(PropertyFromGraphicObjectAccessor),
- 0L,
- false);
-
- // ----- POLYGON
-
- if (error == noErr)
- error = AEInstallObjectAccessor(cPolygon,
- cDocument,
- NewOSLAccessorProc(GraphicObjectFromDocumentAccessor),
- 0L,
- false);
-
- if (error == noErr)
- error = AEInstallObjectAccessor(cPolygon,
- typeWildCard, // for formRelativePosition
- NewOSLAccessorProc(GraphicObjectFromDocumentAccessor),
- 0L,
- false);
-
- if (error == noErr)
- error = AEInstallObjectAccessor(cPolygon,
- cGroupedGraphic,
- NewOSLAccessorProc(GraphicObjectFromGroupAccessor),
- 0L,
- false);
-
- if (error == noErr)
- error = AEInstallObjectAccessor(cProperty,
- cPolygon,
- NewOSLAccessorProc(PropertyFromGraphicObjectAccessor),
- 0L,
- false);
-
- // ----- RECTANGLES
-
- if (error == noErr)
- error = AEInstallObjectAccessor(cRectangle,
- cDocument,
- NewOSLAccessorProc(GraphicObjectFromDocumentAccessor),
- 0L,
- false);
- if (error == noErr)
- error = AEInstallObjectAccessor(cRectangle,
- typeWildCard, // for formRelativePosition
- NewOSLAccessorProc(GraphicObjectFromDocumentAccessor),
- 0L,
- false);
-
- if (error == noErr)
- error = AEInstallObjectAccessor(cRectangle,
- cGroupedGraphic,
- NewOSLAccessorProc(GraphicObjectFromGroupAccessor),
- 0L,
- false);
-
- if (error == noErr)
- error = AEInstallObjectAccessor(cProperty,
- cRectangle,
- NewOSLAccessorProc(PropertyFromGraphicObjectAccessor),
- 0L,
- false);
-
- // ----- ROUND RECTANGLES
-
- if (error == noErr)
- error = AEInstallObjectAccessor(cRoundedRectangle,
- cDocument,
- NewOSLAccessorProc(GraphicObjectFromDocumentAccessor),
- 0L,
- false);
-
- if (error == noErr)
- error = AEInstallObjectAccessor(cRoundedRectangle,
- typeWildCard, // for formRelativePosition
- NewOSLAccessorProc(GraphicObjectFromDocumentAccessor),
- 0L,
- false);
-
- if (error == noErr)
- error = AEInstallObjectAccessor(cRoundedRectangle,
- cGroupedGraphic,
- NewOSLAccessorProc(GraphicObjectFromGroupAccessor),
- 0L,
- false);
-
- if (error == noErr)
- error = AEInstallObjectAccessor(cProperty,
- cRoundedRectangle,
- NewOSLAccessorProc(PropertyFromGraphicObjectAccessor),
- 0L,
- false);
-
- // ----- GRAHIC LINE
-
- if (error == noErr)
- error = AEInstallObjectAccessor(cGraphicLine,
- cDocument,
- NewOSLAccessorProc(GraphicObjectFromDocumentAccessor),
- 0L,
- false);
-
- if (error == noErr)
- error = AEInstallObjectAccessor(cGraphicLine,
- typeWildCard, // for formRelativePosition
- NewOSLAccessorProc(GraphicObjectFromDocumentAccessor),
- 0L,
- false);
-
- if (error == noErr)
- error = AEInstallObjectAccessor(cGraphicLine,
- cGroupedGraphic,
- NewOSLAccessorProc(GraphicObjectFromGroupAccessor),
- 0L,
- false);
-
- if (error == noErr)
- error = AEInstallObjectAccessor(cProperty,
- cGraphicLine,
- NewOSLAccessorProc(PropertyFromGraphicObjectAccessor),
- 0L,
- false);
-
- // --- GROUPED GRAPHICS
-
- if (error == noErr)
- error = AEInstallObjectAccessor(cGroupedGraphic,
- cDocument,
- NewOSLAccessorProc(GraphicObjectFromDocumentAccessor),
- 0L,
- false);
-
- if (error == noErr)
- error = AEInstallObjectAccessor(cGroupedGraphic,
- typeWildCard, // for formRelativePosition
- NewOSLAccessorProc(GraphicObjectFromDocumentAccessor),
- 0L,
- false);
-
- if (error == noErr)
- error = AEInstallObjectAccessor(cGroupedGraphic,
- cGroupedGraphic,
- NewOSLAccessorProc(GraphicObjectFromGroupAccessor),
- 0L,
- false);
-
- if (error == noErr)
- error = AEInstallObjectAccessor(cProperty,
- cGroupedGraphic,
- NewOSLAccessorProc(PropertyFromGraphicObjectAccessor),
- 0L,
- false);
-
- return error;
- }
-
-
- #pragma mark -
- //------------------------------------------------------------------------------
- // Graphic Object From Document Accessor
- //------------------------------------------------------------------------------
- // Retrieve any generic graphic object from a Document container by the key form
-
- static pascal OSErr
- GraphicObjectFromDocumentAccessor(
- DescType desiredClass, // any subclass of cGraphicObject
- const AEDesc* containerToken,
- DescType containerClass,
- DescType keyForm,
- const AEDesc* keyData,
- AEDesc* resultToken, // specified object is returned in result
- long refcon )
- {
- DocumentReference document;
- ElementList list;
- OSErr error;
-
- error = GetDocumentReferenceFromToken(containerToken, &document);
-
- if (error == noErr && document != nil)
- {
- list = GetDocumentElementList(document);
- if (list == nil)
- error = errAENoSuchObject;
- }
-
- if (error == noErr)
- error = GraphicObjectAccessor(list, desiredClass, containerToken, containerClass, keyForm, keyData, resultToken, refcon);
-
- return error;
- }
-
- //------------------------------------------------------------------------------
- // Graphic Object From Group Accessor
- //------------------------------------------------------------------------------
-
- static pascal OSErr
- GraphicObjectFromGroupAccessor(
- DescType desiredClass,
- const AEDesc* containerToken,
- DescType containerClass,
- DescType keyForm,
- const AEDesc* keyData,
- AEDesc* resultToken,
- long refcon)
- {
- OSErr error;
- DocumentReference document = nil;
- ElementReference element = nil;
- ElementList list = nil;
-
- error = GetDocumentReferenceFromToken(containerToken, &document);
-
- if (error == noErr)
- error = GetElementReferenceFromToken(containerToken, &element);
-
- if (error == noErr)
- {
- list = GetSubElementList(element);
- if (list == nil)
- error = errAENoSuchObject;
- }
-
- if (error == noErr)
- error = GraphicObjectAccessor(list, desiredClass, containerToken, containerClass, keyForm, keyData, resultToken, refcon);
-
- return error;
- }
-
- //------------------------------------------------------------------------------
- // Graphic Object From Document Accessor
- // Retrieve any graphic object from a the element list
- // of the specified container by the specified key form
- //------------------------------------------------------------------------------
-
- static pascal OSErr
- GraphicObjectAccessor(
- ElementList list,
- DescType desiredClass, // any subclass of cGraphicObject
- const AEDesc* containerToken,
- DescType containerClass,
- DescType keyForm,
- const AEDesc* keyData,
- AEDesc* resultToken, // specified object is returned in result
- long refcon )
- {
- #pragma unused (containerClass, refcon)
-
- OSErr error = noErr;
-
- DocumentReference document = nil;
-
- long elementNumber = 0L;
- ElementReference element = nil;
- ElementType elementType;
-
- DescType keyDataType = keyData->descriptorType;
- long index;
- long numElements;
- Boolean wantsAllItems = false;
-
- AEDesc startObject = {typeNull, nil}; // These are used to resolve formRange
- AEDesc stopObject = {typeNull, nil};
-
- CoreTokenRecord token;
- InitCoreTokenRecord(&token);
-
- error = GetDocumentReferenceFromToken(containerToken, &document);
- if (error != noErr)
- goto CleanUp;
-
- numElements = CountElementsByClass(list, desiredClass);
-
- switch (keyForm)
- {
- case formUniqueID:
- if (keyDataType == typeLongInteger)
- {
- long uniqueID;
-
- if (DescToLong(keyData, &uniqueID) != noErr)
- {
- error = errAECoercionFail;
- }
- else
- {
- element = FindElementByUniqueID(list, uniqueID);
- if (element == nil)
- error = errAENoSuchObject;
- else if (desiredClass != cGraphicObject)
- {
- // Make sure the element with that ID is really an element of the desired class
-
- ElementType elementType = GetElementType(element);
- DescType objectClass;
- ConvertElementTypeToObjectClass(elementType, &objectClass);
- if (desiredClass != objectClass)
- error = errAENoSuchObject;
- }
- }
- }
- else
- {
- error = errAEWrongDataType;
- }
- break;
-
- case formAbsolutePosition:
- error = NormalizeAbsoluteIndex(keyData, &index, numElements, &wantsAllItems);
- if ((error == noErr) && (wantsAllItems == false))
- {
- error = FindElementByIndex(list, desiredClass, index, &element);
- }
- break;
-
- case formRelativePosition:
- error = ProcessFormRelativePostition(containerToken, keyData, desiredClass, &element);
- break;
-
- case formRange:
- switch (keyDataType)
- {
- case typeRangeDescriptor:
- error = ProcessFormRange((AEDesc *)keyData, &startObject, &stopObject);
- if (error == noErr)
- {
- DescType startType = ExtractDispatchClassFromToken(&startObject);
- DescType stopType = ExtractDispatchClassFromToken(&stopObject);
-
- if (startType != cGraphicObject || stopType != cGraphicObject)
- error = errAEWrongDataType;
- }
- break;
-
- default:
- error = errAEWrongDataType;
- break;
- }
- break;
-
- default:
- return errAEEventNotHandled;
- }
-
- // if user asked for all items, and there aren't any,
- // we'll be kind and return an empty list.
-
- if (wantsAllItems && (error == errAENoSuchObject || error == errAEIllegalIndex))
- {
- error = AECreateList(NULL, 0, false, (AEDescList*)resultToken);
- goto CleanUp;
- }
-
- // fill in the result token
-
- if (error == noErr)
- {
- token.dispatchClass = cGraphicObject;
- token.objectClass = cGraphicObject;
- token.propertyCode = typeNull;
- token.documentNumber = GetDocumentNumber(document);
-
- if (wantsAllItems)
- {
- error = AECreateList(NULL, 0, false, (AEDescList*)resultToken);
-
- if (error == noErr)
- {
- for (index = 1; index <= numElements; index++)
- {
- error = FindElementByIndex(list, desiredClass, index, &element);
- if (error != noErr)
- goto CleanUp;
-
- token.elementNumber = GetElementNumber(element);
-
- error = AEPutPtr(resultToken, 0, desiredClass, &token, sizeof(token));
- if (error != noErr)
- goto CleanUp;
- }
- }
- }
- else if (keyForm == formRange)
- {
- ElementReference beginElement;
- ElementReference endElement;
- ElementType desiredType;
-
- long beginIndex;
- long endIndex;
-
- ConvertObjectClassToElementType(desiredClass, &desiredType);
-
- error = GetElementReferenceFromToken(&startObject, &beginElement);
- if (error != noErr)
- goto CleanUp;
- beginIndex = GetIndexForElementType(document, beginElement, (ElementType)typeWildCard);
-
- error = GetElementReferenceFromToken(&stopObject, &endElement);
- if (error != noErr)
- goto CleanUp;
- endIndex = GetIndexForElementType(document, endElement, (ElementType)typeWildCard);
-
- error = AECreateList(NULL, 0, false, (AEDescList*)resultToken);
- if (error != noErr)
- goto CleanUp;
-
- if (beginIndex > endIndex) // swap elements
- {
- ElementReference temp;
-
- temp = beginElement;
- beginElement = endElement;
- endElement = temp;
- }
-
- element = beginElement;
- while (element != nil)
- {
- elementType = GetElementType(element);
- if (desiredClass == cGraphicObject || elementType == desiredType)
- {
- token.elementNumber = GetElementNumber(element);
-
- error = AEPutPtr(resultToken, 0, desiredClass, &token, sizeof(token));
- if (error != noErr)
- goto CleanUp;
- }
- if (element == endElement)
- break;
- element = GetPreviousElement(element); // because the 1st object is at the end of the list
- }
- }
- else
- {
- token.elementNumber = GetElementNumber(element);
- error = AECreateDesc(desiredClass, &token, sizeof(token), resultToken);
- }
- }
-
- CleanUp:
-
- AEDisposeDesc(&startObject);
- AEDisposeDesc(&stopObject);
-
- return error;
- }
-
- #pragma mark -
- //----------------------------------------------------------------------------------
- // Graphic Object Property Accessor
- //----------------------------------------------------------------------------------
- // Handles properties from ANY graphic object or subclass of cGraphicObject
- //
- // NOTE: The container can be either a single token, or a list of tokens
- //
- //----------------------------------------------------------------------------------
-
- pascal OSErr
- PropertyFromGraphicObjectAccessor( DescType desiredClass,
- const AEDesc* containerToken,
- DescType containerClass,
- DescType keyForm,
- const AEDesc* keyData,
- AEDesc* resultToken,
- long refcon)
- {
- OSErr error;
-
- if (containerToken->descriptorType != typeAEList)
- {
- error = PropertyFromObjectAccessor(desiredClass, containerToken, containerClass, keyForm, keyData, resultToken, refcon);
- }
- else
- {
- error = AECreateList(NULL, 0L, false, resultToken);
- if (error == noErr)
- error = PropertyFromListAccessor(desiredClass, containerToken, containerClass, keyForm, keyData, resultToken, refcon);
- }
-
- return error;
- }
-
- //----------------------------------------------------------------------------------
-
- static OSErr
- PropertyFromListAccessor(
- DescType desiredClass,
- const AEDesc* containerToken,
- DescType containerClass,
- DescType keyForm,
- const AEDesc* keyData,
- AEDesc* resultToken,
- long refcon)
- {
- OSErr error = noErr;
- long index;
- long numItems;
- DescType keyword;
- AEDesc srcItem = {typeNull, nil};
- AEDesc dstItem = {typeNull, nil};
-
- error = AECountItems((AEDescList*)containerToken, &numItems);
- if (error != noErr)
- goto CleanUp;
-
- for (index = 1; index <= numItems; index++)
- {
- error = AEGetNthDesc(containerToken, index, typeWildCard, &keyword, &srcItem);
- if (error != noErr)
- goto CleanUp;
-
- if (srcItem.descriptorType != typeAEList)
- {
- error = PropertyFromObjectAccessor(desiredClass, &srcItem, containerClass, keyForm, keyData, &dstItem, refcon);
- }
- else
- {
- error = AECreateList(NULL, 0L, false, &dstItem);
- if (error == noErr)
- error = PropertyFromListAccessor(desiredClass, &srcItem, containerClass, keyForm, keyData, &dstItem, refcon);
- }
-
- if (error != noErr)
- goto CleanUp;
-
- error = AEPutDesc(resultToken, index, &dstItem);
- if (error != noErr)
- goto CleanUp;
-
- AEDisposeDesc(&srcItem);
- AEDisposeDesc(&dstItem);
- }
-
- CleanUp:
-
- AEDisposeDesc(&srcItem);
- AEDisposeDesc(&dstItem);
-
- return error;
- }
-
- // ----------------------------------------------------------------------------
-
- static OSErr
- PropertyFromObjectAccessor(DescType desiredType, // cProperty
- const AEDesc* containerToken, // single container, or typeAEList of containers
- DescType containerClass, // any subclass of cGraphicObject
- DescType keyForm, // formPropertyID
- const AEDesc* keyData, // dataHandle points to which property
- AEDesc* resultToken,
- long refcon )
- {
- #pragma unused (keyForm, refcon)
-
- OSErr error = noErr;
- DescType requestedProperty = **(DescType**)(keyData->dataHandle);
-
- if (CanGetProperty(containerClass, requestedProperty) || CanSetProperty(containerClass, requestedProperty))
- {
- error = AEDuplicateDesc(containerToken, resultToken);
-
- if (error == noErr)
- {
- resultToken->descriptorType = desiredType;
- (**(CoreTokenHandle)(resultToken->dataHandle)).propertyCode = requestedProperty;
- (**(CoreTokenHandle)(resultToken->dataHandle)).objectClass = containerClass;
- }
- }
- else
- {
- error = errAEEventNotHandled;
- }
-
- return error;
- }
-
- #pragma mark -
-
- // -------------------------------------------------------------------------------------------
- //
- // GetDataFromGraphicObject
- //
- // Given a token that contains information about a graphic object, access the graphic object
- // to extract the relevant data, and return it to the caller in the "data" parameter.
- //
- // PUBLIC: also called from the ObjectComparison callback function
- //
- // The first parameter contains either a single token or a list of tokens
- // The second parameter is NULL or a list of preferred types for the return data
- //
- // -------------------------------------------------------------------------------------------
-
- OSErr
- GetDataFromGraphicObject(AEDesc *tokenOrTokenList, AEDesc *desiredTypes, AEDesc *data)
- {
- OSErr error = noErr;
-
- if (tokenOrTokenList->descriptorType != typeAEList)
- {
- error = GetDataFromObject(tokenOrTokenList, desiredTypes, data);
- }
- else
- {
- error = AECreateList(NULL, 0L, false, data);
- if (error == noErr)
- error = GetDataFromList(tokenOrTokenList, desiredTypes, data);
- }
-
- return error;
- }
-
- // -------------------------------------------------------------------------------------------
- //
- // GetDataFromList
- //
- // Given a list of objects, replicate the list structure and replace the tokens
- // with a list of the requested data from each token
- //
- // -------------------------------------------------------------------------------------------
-
- static OSErr
- GetDataFromList(AEDesc *srcList, AEDesc *desiredTypes, AEDesc *dstList)
- {
- OSErr error = noErr;
- long index;
- long numItems;
- DescType keyword;
- AEDesc srcItem = {typeNull, nil};
- AEDesc dstItem = {typeNull, nil};
-
- error = AECountItems((AEDescList*)srcList, &numItems);
- if (error != noErr)
- goto CleanUp;
-
- for (index = 1; index <= numItems; index++)
- {
- error = AEGetNthDesc(srcList, index, typeWildCard, &keyword, &srcItem);
- if (error != noErr)
- goto CleanUp;
-
- if (srcItem.descriptorType != typeAEList)
- {
- error = GetDataFromObject(&srcItem, desiredTypes, &dstItem); // Get data from single item
- }
- else
- {
- error = AECreateList(NULL, 0L, false, &dstItem);
- if (error == noErr)
- error = GetDataFromList(&srcItem, desiredTypes, &dstItem);
- }
- if (error != noErr)
- goto CleanUp;
-
- error = AEPutDesc(dstList, index, &dstItem);
- if (error != noErr)
- goto CleanUp;
-
- AEDisposeDesc(&srcItem);
- AEDisposeDesc(&dstItem);
- }
-
- CleanUp:
-
- AEDisposeDesc(&srcItem);
- AEDisposeDesc(&dstItem);
-
- return error;
- }
-
- //----------------------------------------------------------------------------------
- // GetDataFromObject
- // Get the data from one object
- //----------------------------------------------------------------------------------
-
- static OSErr
- GetDataFromObject(AEDesc *token, AEDesc *desiredTypes, AEDesc *data)
- {
- OSErr error = noErr;
-
- DocumentReference document = nil;
- ElementReference element = nil;
-
- ElementType elementType;
- DescType objectClass;
- DescType propertyCode;
-
- Handle textH = nil;
- char *text = NULL;
-
- long aLong;
- short aShort;
- Rect aRect;
- Point aPoint;
- short double aShortDouble;
-
- RGBColor aRGBColor;
- ColorRecord aColor;
- Boolean foundIt;
-
- DescType mostDesiredType = typeNull;
-
- error = GetDocumentReferenceFromToken(token, &document);
- if (error != noErr)
- goto CleanUp;
-
- error = GetElementReferenceFromToken(token, &element);
- if (error != noErr)
- goto CleanUp;
-
- elementType = GetElementType(element);
-
- propertyCode = ExtractPropertyCodeFromToken(token);
-
- ConvertElementTypeToObjectClass(elementType, &objectClass);
-
- if (desiredTypes != NULL && desiredTypes->descriptorType != typeNull)
- {
- long numItems;
- AEKeyword keyword;
- DescType actualType;
- long actualSize;
-
- error = AECountItems(desiredTypes, &numItems);
- if (error == noErr)
- {
- error = AEGetNthPtr(desiredTypes, 1L, typeType, &keyword, &actualType, &mostDesiredType, sizeof(DescType), &actualSize);
- }
- }
-
- switch (propertyCode)
- {
- // -------------------------------------------------------------------------------
- // Base object properties
- // -------------------------------------------------------------------------------
-
- case pBestType:
- case pClass:
- case pDefaultType:
- case pObjectType:
- error = AECreateDesc(typeType, &objectClass, sizeof(DescType), data);
- break;
-
- case pProperties:
- {
- error = AECreateList(NULL, 0L, true, data);
- if (error != noErr)
- goto CleanUp;
-
- // now, add each property to the above record
-
- error = AEPutKeyPtr(data, pObjectType, typeType, &objectClass, sizeof(DescType));
-
- aLong = GetElementNumber(element);
- error = AEPutKeyPtr(data, pID, typeLongInteger, &aLong, sizeof(long));
-
- aRect = GetElementBoundingBox(element);
- error = AEPutKeyPtr(data, pBounds, typeQDRectangle, &aRect, sizeof(Rect));
-
- aPoint = topLeft(aRect); // NOTE: depends on the GetElementBoundingBox directly above!!!
- error = AEPutKeyPtr(data, pLocation, typeQDPoint, &aPoint, sizeof(Point));
-
- aShort = aRect.right - aRect.left;
- error = AEPutKeyPtr(data, pWidth, typeShortInteger, &aShort, sizeof(short));
-
- aShort = aRect.bottom - aRect.top;
- error = AEPutKeyPtr(data, pHeight, typeShortInteger, &aShort, sizeof(short));
-
- // stroke props
-
- aShortDouble = (short double)GetElementStrokePenWidth(element);
- error = AEPutKeyPtr(data, pStrokeSize, typeFloat, &aShortDouble, sizeof(short double));
-
- aRGBColor = GetElementStrokeColor(element);
- foundIt = GetColorRecordByRGB(aRGBColor, &aColor);
- if (foundIt)
- error = AEPutKeyPtr(data, pStrokeColor, typeEnumerated, &aColor.code, sizeof(DescType));
- else
- error = AEPutKeyPtr(data, pStrokeColor, typeRGBColor, &aRGBColor, sizeof(RGBColor));
-
- // fill props
-
- aRGBColor = GetElementFillColor(element);
- foundIt = GetColorRecordByRGB(aRGBColor, &aColor);
- if (foundIt)
- error = AEPutKeyPtr(data, pFillColor, typeEnumerated, &aColor.code, sizeof(DescType));
- else
- error = AEPutKeyPtr(data, pFillColor, typeRGBColor, &aRGBColor, sizeof(RGBColor));
-
- // Polygons only
-
- if (elementType == kQDPolygon)
- {
- AEDesc pointList = {typeNull, nil};
-
- // Extract the points from the polygon and build a typeAEList object
-
- error = AECreateList(nil, (Size)0, false, &pointList); // create an empty list to hold the Points
-
- if (error == noErr)
- {
- PolyHandle polyHandle = GetElementPolygon(element);
- if (polyHandle != nil)
- {
- short numPoints = CountPolygonPoints(polyHandle);
- short pointNum;
-
- for (pointNum = 1; pointNum <= numPoints; pointNum++)
- {
- aPoint = GetPolygonPoint(polyHandle, pointNum);
- error = AEPutPtr(&pointList, pointNum, typeQDPoint, &aPoint, sizeof(Point));
- if (error != noErr)
- goto CleanUp;
- }
- }
- }
-
- if (error == noErr)
- error = AEPutKeyDesc(data, pPointList, &pointList);
-
- AEDisposeDesc(&pointList);
- }
-
- // Rounded Rects only
-
- if (elementType == kQDRoundRect)
- {
- aShort = GetElementRoundRectOvalSize(element).v;
- error = AEPutKeyPtr(data, pCornerCurveHeight, typeShortInteger, &aShort, sizeof(short));
-
- aShort = GetElementRoundRectOvalSize(element).h;
- error = AEPutKeyPtr(data, pCornerCurveWidth, typeShortInteger, &aShort, sizeof(short));
- }
-
- // Graphic Line only
-
- if (elementType == kQDLine)
- {
- aPoint = GetElementLineBeginPoint(element);
- error = AEPutKeyPtr(data, pStartPoint, typeQDPoint, &aPoint, sizeof(Point));
-
- aPoint = GetElementLineBeginPoint(element);
- error = AEPutKeyPtr(data, pStartPoint, typeQDPoint, &aPoint, sizeof(Point));
- }
- }
- break;
-
- case pContents:
- switch (elementType)
- {
- case kGroup:
- {
- ElementList list = GetSubElementList(element);
- ElementReference subElement;
- AEDesc subElementOSpec = {typeNull, nil};
-
- if (list == nil)
- error = errAENoSuchObject;
-
- if (error == noErr)
- error = AECreateList(NULL, 0L, false, data);
-
- if (error == noErr)
- {
- for (subElement = GetFirstElement(list); subElement != nil; subElement = GetNextElement(subElement))
- {
- error = CreateGraphicGroupMemberOSpec(document, element, subElement, &subElementOSpec);
- if (error != noErr)
- break;
-
- error = AEPutDesc(data, 0L, &subElementOSpec);
- if (error != noErr)
- break;
-
- AEDisposeDesc(&subElementOSpec);
- }
- }
-
- if (error != noErr)
- AEDisposeDesc(data);
-
- AEDisposeDesc(&subElementOSpec);
- }
- break;
-
- default:
- error = errAECantSupplyType;
- break;
- }
- break;
-
- // -------------------------------------------------------------------------------
- // Graphic object properties
- // -------------------------------------------------------------------------------
-
- case pID:
- aLong = GetElementNumber(element);
- error = AECreateDesc(typeLongInteger, &aLong, sizeof(long), data);
- break;
-
- case pBounds:
- aRect = GetElementBoundingBox(element);
- error = AECreateDesc(typeQDRectangle, &aRect, sizeof(Rect), data);
- break;
-
- case pLocation:
- aRect = GetElementBoundingBox(element);
- aPoint = topLeft(aRect);
- error = AECreateDesc(typeQDPoint, &aPoint, sizeof(Point), data);
- break;
-
- case pWidth:
- aRect = GetElementBoundingBox(element);
- aShort = aRect.right - aRect.left;
- error = AECreateDesc(typeShortInteger, &aShort, sizeof(short), data);
- break;
-
- case pHeight:
- aRect = GetElementBoundingBox(element);
- aShort = aRect.bottom - aRect.top;
- error = AECreateDesc(typeShortInteger, &aShort, sizeof(short), data);
- break;
-
- // -------------------------------------------------------------------------------
- // Stroke
- // -------------------------------------------------------------------------------
-
- case pStrokeSize:
- aShortDouble = (short double)GetElementStrokePenWidth(element);
- error = AECreateDesc(typeFloat, &aShortDouble, sizeof(short double), data);
- break;
-
- case pStrokeColor:
- aRGBColor = GetElementStrokeColor(element);
-
- foundIt = GetColorRecordByRGB(aRGBColor, &aColor);
-
- switch (mostDesiredType)
- {
- case typeEnumerated:
- case typeType:
- if (foundIt)
- error = AECreateDesc(typeEnumerated, &aColor.code, sizeof(DescType), data);
- else
- error = errAECantSupplyType;
- break;
-
- case typeChar:
- case typeIntlText:
- if (foundIt)
- error = AECreateDesc(typeChar, aColor.name, strlen(aColor.name), data);
- else
- error = errAECantSupplyType;
- break;
-
- default:
- case typeNull:
- case typeWildCard:
- case typeBest:
- case typeRGBColor:
- error = AECreateDesc(typeRGBColor, &aRGBColor, sizeof(RGBColor), data);
- break;
- }
- break;
-
- // -------------------------------------------------------------------------------
- // Fill
- // -------------------------------------------------------------------------------
-
- case pFillColor:
- aRGBColor = GetElementFillColor(element);
- foundIt = GetColorRecordByRGB(aRGBColor, &aColor);
-
- switch (mostDesiredType)
- {
- case typeEnumerated:
- case typeType:
- if (foundIt)
- error = AECreateDesc(typeEnumerated, &aColor.code, sizeof(DescType), data);
- else
- error = errAECantSupplyType;
- break;
-
- case typeChar:
- case typeIntlText:
- if (foundIt)
- error = AECreateDesc(typeChar, aColor.name, strlen(aColor.name), data);
- else
- error = errAECantSupplyType;
- break;
-
- default:
- case typeNull:
- case typeWildCard:
- case typeBest:
- case typeRGBColor:
- error = AECreateDesc(typeRGBColor, &aRGBColor, sizeof(RGBColor), data);
- break;
- }
-
- break;
-
- // -------------------------------------------------------------------------------
- // for cPolygon only
- // -------------------------------------------------------------------------------
-
- case pPointList:
- if (GetElementType(element) != kQDPolygon)
- {
- error = errAECantSupplyType;
- break;
- }
-
- // Extract the points from the polygon and build a typeAEList object
-
- error = AECreateList(nil, (Size)0, false, data); // create an empty list to hold the Points
- if (error == noErr)
- {
- PolyHandle polyHandle = GetElementPolygon(element);
- if (polyHandle != nil)
- {
- short numPoints = CountPolygonPoints(polyHandle);
- short pointNum;
-
- for (pointNum = 1; error == noErr && pointNum <= numPoints; pointNum++)
- {
- aPoint = GetPolygonPoint(polyHandle, pointNum);
- error = AEPutPtr(data, pointNum, typeQDPoint, &aPoint, sizeof(Point));
- }
- }
- }
- break;
-
- // -------------------------------------------------------------------------------
- // for cRoundedRectangle only
- // -------------------------------------------------------------------------------
-
- case pCornerCurveHeight:
- if (GetElementType(element) != kQDRoundRect)
- {
- error = errAECantSupplyType;
- break;
- }
- aShort = GetElementRoundRectOvalSize(element).v;
- error = AECreateDesc(typeShortInteger, &aShort, sizeof(short), data);
- break;
-
- case pCornerCurveWidth:
- if (GetElementType(element) != kQDRoundRect)
- {
- error = errAECantSupplyType;
- break;
- }
- aShort = GetElementRoundRectOvalSize(element).h;
- error = AECreateDesc(typeShortInteger, &aShort, sizeof(short), data);
- break;
-
- // -------------------------------------------------------------------------------
- // for cGraphicLine only (also uses pen items above)
- // -------------------------------------------------------------------------------
-
- case pStartPoint:
- if (GetElementType(element) != kQDLine)
- {
- error = errAECantSupplyType;
- break;
- }
- aPoint = GetElementLineBeginPoint(element);
- error = AECreateDesc(typeQDPoint, &aPoint, sizeof(Point), data);
- break;
-
- case pEndPoint:
- if (GetElementType(element) != kQDLine)
- {
- error = errAECantSupplyType;
- break;
- }
-
- aPoint = GetElementLineBeginPoint(element);
- error = AECreateDesc(typeQDPoint, &aPoint, sizeof(Point), data);
- break;
-
-
- // -------------------------------------------------------------------------------
- // for cGroupedGraphic only
- // -------------------------------------------------------------------------------
-
- case pGraphicObjects:
- // Returns a list of ospec records for the objects in the group,
- // with the frontmost object first, etc.
- if (GetElementType(element) != kGroup)
- {
- error = errAECantSupplyType;
- break;
- }
-
- // Build a typeAEList object containing references to the objects
-
- error = AECreateList(nil, (Size)0, false, data); // create an empty list to hold the Points
- if (error == noErr)
- {
- ElementList list = GetSubElementList(element);
- ElementReference subElement;
- AEDesc subElementOSpec = {typeNull, nil};
-
- if (list == nil)
- error = errAENoSuchObject;
-
- if (error == noErr)
- error = AECreateList(NULL, 0L, false, data);
-
- if (error == noErr)
- {
- for (subElement = GetFirstElement(list); subElement != nil; subElement = GetNextElement(subElement))
- {
- error = CreateGraphicGroupMemberOSpec(document, element, subElement, &subElementOSpec);
- if (error != noErr)
- break;
-
- error = AEPutDesc(data, 0L, &subElementOSpec);
- if (error != noErr)
- break;
-
- AEDisposeDesc(&subElementOSpec);
- }
- }
-
- if (error != noErr)
- AEDisposeDesc(data);
-
- AEDisposeDesc(&subElementOSpec);
- }
- break;
-
- deafult:
- error = errAECantSupplyType;
- }
-
- CleanUp:
-
- return error;
- }
-
- #pragma mark -
- // -------------------------------------------------------------------------------------------
- //
- // SetDataForList
- //
- // Given a token that contains a list of cGraphicObject tokens,
- // walk the list recursively to set the data for each token in the list
- //
- // -------------------------------------------------------------------------------------------
-
- static OSErr
- SetDataForList(AEDesc *token, AEDesc *data)
- {
- OSErr error = noErr;
- AEDesc tempToken = {typeNull, nil};
-
- long numItems;
- long index;
- AEKeyword keyword;
-
-
- if (token->descriptorType != typeAEList)
- {
- error = SetDataForObject(token, data);
- }
- else
- {
- error = AECountItems((AEDescList*)token, &numItems);
- if (error != noErr)
- goto CleanUp;
-
- for (index = 1; index <= numItems; index++)
- {
- error = AEGetNthDesc((AEDescList*)token, index, typeWildCard, &keyword, &tempToken);
- if (error != noErr)
- goto CleanUp;
-
- if (tempToken.descriptorType != typeAEList)
- {
- error = SetDataForObject(&tempToken, data); // Set data from single item
- }
- else
- {
- error = SetDataForList(&tempToken, data); // Recurse sublist
- }
- if (error != noErr)
- goto CleanUp;
-
- AEDisposeDesc(&tempToken);
- }
- }
-
- CleanUp:
-
- AEDisposeDesc(&tempToken);
-
- return error;
- }
-
- //----------------------------------------------------------------------------------
- // SetDataForObject
- //----------------------------------------------------------------------------------
- // Assumption: HandleSetData() has already filtered out all attempts
- // to write to a read-only property, so we only handle the writeable properties here.
-
- static OSErr
- SetDataForObject(AEDesc *token, AEDesc *data)
- {
-
- OSErr error = noErr;
-
- DocumentReference document = nil;
- ElementReference element = nil;
- ElementType elementType;
-
- Boolean usePropertyCode;
- DescType propertyCode;
-
- AEDesc propertyRecord = {typeNull, nil};
-
- error = GetDocumentReferenceFromToken(token, &document);
- if (error != noErr)
- goto CleanUp;
-
- error = GetElementReferenceFromToken(token, &element);
- if (error != noErr)
- goto CleanUp;
-
- elementType = GetElementType(element);
-
- usePropertyCode = ExtractUsePropertyCodeFromToken(token);
-
- if (usePropertyCode)
- {
- propertyCode = ExtractPropertyCodeFromToken(token);
-
- // Convert the single property to a record containing one property
-
- if (data->descriptorType == typeAERecord)
- {
- error = SetProperties(document, element, data);
- }
- else // Build a record with one property
- {
- error = AECreateList(NULL, 0L, true, &propertyRecord);
- if (error != noErr)
- goto CleanUp;
-
- error = AEPutKeyDesc(&propertyRecord, propertyCode, data);
- if (error != noErr)
- goto CleanUp;
-
- error = SetProperties(document, element, &propertyRecord);
- }
- }
-
- // Draw the element with its new data
-
- if (error == noErr)
- {
- IMDraw(document);
- }
-
- CleanUp:
-
- AEDisposeDesc(&propertyRecord);
-
- if (error == noErr)
- MarkDocumentAsChanged(document);
-
- return error;
- }
-
- //----------------------------------------------------------------------------------
- // SetProperties
- //----------------------------------------------------------------------------------
- // Set an object's properties from the record we receive
-
- static OSErr
- SetProperties(DocumentReference document, ElementReference element, AEDesc *propertyRecord)
- {
- OSErr error = noErr;
- OSErr ignoreError = noErr;
-
- long numProperties = 0L;
-
- ElementType elementType = GetElementType(element);
-
- AEDesc data = {typeNull, nil};
-
- // Used in setting boundingBox for groups
-
- Rect boundingBox;
- Rect newBoundingBox;
- short corner;
- Point mousePt = {0,0};
-
- if (propertyRecord == NULL || propertyRecord->descriptorType != typeAERecord)
- {
- error = errAEWrongDataType;
- goto CleanUp;
- }
-
- error = AECountItems(propertyRecord, &numProperties);
-
- if (error != noErr || numProperties <= 0)
- goto CleanUp;
-
- // ----------------------------- Bounding box of the new element ------------------------------
- // pBounds
-
- ignoreError = AEGetKeyDesc(propertyRecord, pBounds, typeQDRectangle, &data);
- if (ignoreError != errAEDescNotFound)
- {
- error = DescToRect(&data, &newBoundingBox);
-
- if (error == noErr)
- {
- switch (elementType)
- {
- case kQDPolygon:
- {
- PolyHandle polygon = GetElementPolygon(element);
-
- boundingBox = GetElementBoundingBox(element);
-
- if (polygon == nil)
- {
- SetElementBoundingBox(element, newBoundingBox);
- }
- else
- {
- MapPoly(polygon, &boundingBox, &newBoundingBox);
- SetElementBoundingBox(element, newBoundingBox);
- SetElementPolygon(element, polygon);
- }
- }
- break;
-
- case kGroup:
- {
- boundingBox = GetElementBoundingBox(element);
- corner = 0;
-
- // First, resize the group, if necessary
-
- ResizeElementData(document, element, newBoundingBox);
-
- // Then, move the group, if necessary
-
- if ((newBoundingBox.left != boundingBox.left) || (newBoundingBox.top != boundingBox.top))
- MoveElementData(document, element, newBoundingBox.top, newBoundingBox.left);
- }
- break;
-
- default:
- SetElementBoundingBox(element, newBoundingBox);
- break;
- }
- }
- }
-
- // pLocation
-
- ignoreError = AEGetKeyDesc(propertyRecord, pLocation, typeQDPoint, &data);
- if (ignoreError != errAEDescNotFound)
- {
- Point upperLeft;
- error = DescToPoint(&data, &upperLeft);
-
- if (error == noErr)
- {
- MoveElementData(document, element, upperLeft.v, upperLeft.h);
- }
- }
-
- // pWidth
-
- ignoreError = AEGetKeyDesc(propertyRecord, pWidth, typeShortInteger, &data);
- if (ignoreError != errAEDescNotFound)
- {
- short width;
- error = DescToShort(&data, &width);
-
- if (error == noErr)
- {
- boundingBox = GetElementBoundingBox(element);
- boundingBox.right = boundingBox.left + width;
- SetElementBoundingBox(element, boundingBox);
- }
- AEDisposeDesc(&data);
- }
-
- // pHeight
-
- ignoreError = AEGetKeyDesc(propertyRecord, pHeight, typeShortInteger, &data);
- if (ignoreError != errAEDescNotFound)
- {
- short height;
- error = DescToShort(&data, &height);
-
- if (error == noErr)
- {
- boundingBox = GetElementBoundingBox(element);
- boundingBox.bottom = boundingBox.top + height;
- SetElementBoundingBox(element, boundingBox);
- }
- AEDisposeDesc(&data);
- }
-
-
- // ----------------------------- Stroke ------------------------------
-
- // pStrokeSize
-
- ignoreError = AEGetKeyDesc(propertyRecord, pStrokeSize, typeFloat, &data);
- if (ignoreError != errAEDescNotFound)
- {
- short double penSize = 1.0;
- error = DescToShortDouble(&data, &penSize);
-
- if (error == noErr)
- {
- SetElementStrokePenWidth(element, (float)penSize);
- SetElementStrokePenHeight(element, (float)penSize);
- }
- AEDisposeDesc(&data);
- }
-
- // pStrokeColor
- // colors can be supplied as RGB values, a color name, or a color enumeration
- // Coercion handlers are called automatically for a color name or a color enumeration
-
- ignoreError = AEGetKeyDesc(propertyRecord, pStrokeColor, typeRGBColor, &data);
- if (ignoreError != errAEDescNotFound)
- {
- RGBColor rgb;
- error = DescToRGBColor(&data, &rgb);
-
- if (error == noErr)
- {
- SetElementStrokeColor(element, rgb);
- }
-
- AEDisposeDesc(&data);
- }
-
- // ----------------------------- Fill ------------------------------
-
- // pFillColor
- // colors can be supplied as RGB values, a color name, or a color enumeration
- // Coercion handlers are called automatically for a color name or a color enumeration
-
- ignoreError = AEGetKeyDesc(propertyRecord, pFillColor, typeRGBColor, &data);
- if (ignoreError != errAEDescNotFound)
- {
- RGBColor rgb;
-
- error = DescToRGBColor(&data, &rgb);
-
- if (error == noErr)
- {
- SetElementFillColor(element, rgb);
- }
- AEDisposeDesc(&data);
- }
-
-
- // ----------------------------- Rounded Rectangle ------------------------------
-
- if (elementType == kQDRoundRect)
- {
- // oval height
-
- ignoreError = AEGetKeyDesc(propertyRecord, pCornerCurveHeight, typeShortInteger, &data);
- if (ignoreError != errAEDescNotFound)
- {
- short height;
- error = DescToShort(&data, &height);
-
- if (error == noErr)
- {
- Point ovalSize = GetElementRoundRectOvalSize(element);
- ovalSize.v = height;
- SetElementRoundRectOvalSize(element, ovalSize);
- }
- AEDisposeDesc(&data);
- }
-
- // oval width
-
- ignoreError = AEGetKeyDesc(propertyRecord, pCornerCurveWidth, typeShortInteger, &data);
- if (ignoreError != errAEDescNotFound)
- {
- short width;
- error = DescToShort(&data, &width);
-
- if (error == noErr)
- {
- Point ovalSize = GetElementRoundRectOvalSize(element);
- ovalSize.h = width;
- SetElementRoundRectOvalSize(element, ovalSize);
- }
- AEDisposeDesc(&data);
- }
- }
-
- // ----------------------------- Line ------------------------------
-
- if (elementType == kQDLine)
- {
- Point point;
-
- //start point
-
- ignoreError = AEGetKeyDesc(propertyRecord, pStartPoint, typeQDPoint, &data);
- if (ignoreError != errAEDescNotFound)
- {
- error = DescToPoint(&data, &point);
-
- if (error == noErr)
- SetElementLineBeginPoint(element, point);
-
- AEDisposeDesc(&data);
- }
-
- // end point
-
- ignoreError = AEGetKeyDesc(propertyRecord, pEndPoint, typeQDPoint, &data);
- if (ignoreError != errAEDescNotFound)
- {
- Point point;
- error = DescToPoint(&data, &point);
-
- if (error == noErr)
- SetElementLineEndPoint(element, point);
-
- AEDisposeDesc(&data);
- }
-
- boundingBox = CalculateElementBounds(element);
- SetElementBoundingBox(element, boundingBox);
-
- }
-
- // ----------------------------- Group ------------------------------
-
- if (elementType == kGroup)
- {
- // pGraphicObjects -- ex: set properties to {members: {oval 1, oval 2, rectangle 3}}
-
- ignoreError = AEGetKeyDesc(propertyRecord, pGraphicObjects, typeAEList, &data);
- if (ignoreError != errAEDescNotFound)
- {
- error = MakeGroupFromAEList(document, element, &data);
- if (error != noErr)
- {
- DestroyElement(element);
- goto CleanUp;
- }
- AEDisposeDesc(&data);
- }
- }
-
- // ----------------------------- Polygon ------------------------------
-
- if (elementType == kQDPolygon)
- {
- // point list
-
- ignoreError = AEGetKeyDesc(propertyRecord, pPointList, typeAEList, &data);
- if (ignoreError != errAEDescNotFound)
- {
- error = MakePolygonFromAEPointList(document, element, &data);
- AEDisposeDesc(&data);
- }
-
- }
-
- CleanUp:
-
- AEDisposeDesc(&data);
-
- return error;
- }
-
- #pragma mark -
- //----------------------------------------------------------------------------------
- // MakeNewObject
- //----------------------------------------------------------------------------------
- // Assumption: HandleCreateElement() has already filtered out all attempts
- // to write to create the wrong type of object for the container
-
- // NOTE: the token can be a null descriptor {typeNull, nil}, in which case there is
- // no ospec for the insertion location.
-
- static OSErr
- MakeNewObject(const DescType objectToCreate,
- const DescType insertionPosition,
- const AEDesc *token,
- const AEDesc *ptrToWithData,
- const AEDesc *ptrToWithProperties,
- AppleEvent *reply)
- {
- OSErr error = noErr;
- OSErr ignoreError = noErr;
-
- DocumentReference document = nil;
- ElementReference element = nil;
- ElementReference oldElement = nil;
- ElementType elementType;
-
- error = GetDocumentReferenceFromToken(token, &document);
- if (error == errAENoSuchObject)
- {
- document = GetFrontDocument(GetDocumentList());
- error = (document == nil) ? errAENoSuchObject : noErr;
- }
-
- // we don't necessarily have an element because we could be creating the first element
- // or we could have asked to create a new element "at beginning of document 1", etc.
-
- if (error == noErr)
- {
- error = GetElementReferenceFromToken(token, &oldElement);
-
- if (error == errAENoSuchObject)
- {
- error = noErr;
- oldElement = GetFirstElement(GetDocumentElementList(document));
- }
- }
-
- if (error == noErr)
- {
- error = ConvertObjectClassToElementType(objectToCreate, &elementType);
-
- if (error == noErr)
- {
- element = CreateElement(GetDocumentElementList(document), elementType);
- error = ElementError();
- if (error == noErr && element != nil)
- {
- PopulateElementWithDefaultData(element);
- }
- }
-
- // By default, elements are created at the end of the list
- // If insertionPosition == kAEBeginning, then all is OK,
- // otherwise we should orphan the new element and relocate it accordingly.
-
- // NOTE: it seems like calls to ...InsertingBefore and ...InsertingAfter
- // are backwards, but they're not because the appleevent constants are from
- // the users point of view - "after" means "behind", "before" means "in front of"
- // The element list, however, is sorted from back (1st created) to front (most-recently created),
- // so that InsertingBefore an element actually places it behind that element visually.
-
- if (error == noErr)
- {
- switch (insertionPosition)
- {
- case kAEBeginning:
- // default behavior creates element as frontmost object
- error = noErr; // Just so the debugger can single step and stop here.
- break;
-
- case kAEEnd:
- if (oldElement != nil && element != oldElement)
- {
- OrphanElement(element);
- AdoptOrphanInsertingBeforeElement(element, oldElement);
- }
- break;
-
- case kAEBefore:
- if (oldElement != nil && element != oldElement)
- {
- OrphanElement(element);
- AdoptOrphanInsertingAfterElement(element, oldElement);
- }
- break;
-
- case kAEAfter:
- if (oldElement != nil && element != oldElement)
- {
- OrphanElement(element);
- AdoptOrphanInsertingBeforeElement(element, oldElement);
- }
- break;
-
- case kAEReplace:
- if (oldElement != nil && element != oldElement)
- {
- OrphanElement(element);
- AdoptOrphanInsertingAfterElement(element, oldElement);
- DestroyElement(oldElement);
- }
- break;
-
- default:
- SysBeep(2);
- break;
- }
- }
-
- // ==================================================================================
- // First, insert any data we received
- // ==================================================================================
-
- if (error == noErr && ptrToWithData != NULL)
- {
- DescType dataType = ptrToWithData->descriptorType;
- Handle dataSource = ptrToWithData->dataHandle;
-
- switch (dataType)
- {
- case typeNull:
- break;
-
- case typeChar:
- switch (GetElementType(element))
- {
- default:
- break; // we don't support data for elements yet
- }
- break;
-
- default:
- break;
- }
- }
-
- // ==================================================================================
- // Now, apply properties, if we received any.
- // ==================================================================================
-
- if (error == noErr && ptrToWithProperties != NULL)
- {
- error = SetProperties(document, element, (AEDesc *)ptrToWithProperties);
- }
-
- // if we created the new element, draw it
-
- if (error == noErr && element != nil)
- {
- IMDraw(document);
- MarkDocumentAsChanged(document);
- }
-
- }
-
- // return a reference to the new graphic object in the AppleEvent reply parameter
-
- if (error == noErr && reply != NULL && document != nil && element != nil)
- {
- AEDesc ospec = {typeNull, nil};
-
- error = CreateGraphicObjectOSpec(document, element, &ospec);
-
- if (error == noErr)
- {
- AEPutParamDesc(reply, keyDirectObject, &ospec);
- }
-
- AEDisposeDesc(&ospec);
- }
-
- CleanUp:
-
- return error;
- }
-
- #pragma mark -
- //----------------------------------------------------------------------------------
- // Typically something like "move <rectangle 1> to <after> <oval 2>"
-
- OSErr
- DoMove(AEDesc *moveToken, DescType insertionPos, AEDesc *toToken)
- {
-
- OSErr error = noErr;
- Boolean movedIt = false;
-
- DescType moveTokenType = moveToken->descriptorType;
- DescType toTokenType = toToken->descriptorType;
-
- DocumentReference document = nil;
- ElementReference moveElement = nil;
- ElementReference toElement = nil;
-
- GetDocumentReferenceFromToken(moveToken, &document);
- GetElementReferenceFromToken(moveToken, &moveElement);
-
- if (moveTokenType != typeNull)
- GetElementReferenceFromToken(toToken, &toElement);
-
- switch (insertionPos)
- {
- case kAEBeginning:
- // Get the last (frontmost) element, but make sure it's not the
- // element we are trying to move
- toElement = GetFirstElement(GetDocumentElementList(document));
- while (GetNextElement(toElement) != nil)
- toElement = GetNextElement(toElement);
- if (toElement != nil && toElement != moveElement)
- {
- OrphanElement(moveElement);
- AdoptOrphanInsertingAfterElement(moveElement, toElement);
- movedIt = true;
- }
-
- break;
-
- case kAEEnd:
- toElement = GetFirstElement(GetFirstElement(GetDocumentElementList(document)));
- if (toElement != nil && toElement != moveElement)
- {
- OrphanElement(moveElement);
- AdoptOrphanInsertingBeforeElement(moveElement, toElement);
- movedIt = true;
- }
- break;
-
- case kAEBefore:
- if (toElement != nil && toElement != moveElement)
- {
- OrphanElement(moveElement);
- AdoptOrphanInsertingAfterElement(moveElement, toElement);
- movedIt = true;
- }
- break;
-
- case kAEAfter:
- if (toElement != nil && toElement != moveElement)
- {
- OrphanElement(moveElement);
- AdoptOrphanInsertingBeforeElement(moveElement, toElement);
- movedIt = true;
- }
- break;
-
- case kAEReplace:
- if (toElement != nil && toElement != moveElement)
- {
- OrphanElement(moveElement);
- AdoptOrphanInsertingAfterElement(moveElement, toElement);
- DestroyElement(toElement);
- toElement = nil;
- movedIt = true;
- }
- break;
-
- default:
- SysBeep(2);
- break;
- }
-
- if (movedIt)
- {
- IMDraw(document);
- MarkDocumentAsChanged(document);
- }
-
- return error;
- }
-
-
- #pragma mark -
- //----------------------------------------------------------------------------------
-
- #define kMaximumPolygonPoints 400
-
- static OSErr
- MakePolygonFromAEPointList(DocumentReference document, ElementReference element, AEDescList* list)
- {
- #pragma unused (document)
-
- OSErr error;
-
- Point aPoint;
- Point zeroPoint = {0,0};
- Point pointList[kMaximumPolygonPoints];
- long index;
- long numPoints;
- AEKeyword keyword;
- DescType actualType;
- Size actualSize;
-
- PolyHandle polygon = nil;
-
- error = AECountItems(list, &numPoints);
-
- if (error == noErr && numPoints > kMaximumPolygonPoints)
- error = errAEEventNotHandled;
-
- if (error == noErr)
- {
- for (index = 1; index <= numPoints; index++)
- {
- error = AEGetNthPtr(list, index, typeQDPoint,
- &keyword, &actualType,
- &aPoint, sizeof(aPoint),
- &actualSize);
- if (error == noErr)
- pointList[index-1] = aPoint;
- else
- pointList[index-1] = zeroPoint;
- }
- }
-
- if (error == noErr)
- {
- polygon = CreatePolygonFromPoints(numPoints, pointList);
-
- if (polygon == nil)
- {
- error = errAEEventNotHandled;
- }
- else
- {
- SetElementPolygon(element, polygon);
- SetElementBoundingBox(element, (**polygon).polyBBox);
- }
- }
-
- return error;
- }
-
- //----------------------------------------------------------------------------------
- // On entry, the element is an empty group element and the object specifiers in
- // the list are the objects that will be added to the new group
-
- #define MAX_GROUP_MEMBERS 100
-
- static OSErr
- MakeGroupFromAEList(DocumentReference document, ElementReference group, AEDescList* list)
- {
- OSErr error;
-
- long index;
- long numObjects;
- AEKeyword keyword;
-
- AEDesc ospec = {typeNull, nil};
- AEDesc token = {typeNull, nil};
-
- ElementReference member[MAX_GROUP_MEMBERS];
- long memberIndex = 0;
-
- Assert(GetElementType(group) == kGroup, "Element passed in is not a group");
-
- error = AECountItems(list, &numObjects);
- if (error != noErr || numObjects < 2)
- {
- error = errAEEventNotHandled;
- goto CleanUp;
- }
-
- // This is divided into two steps. The first just builds a list of element references
- // for those elements that will be added to the list.
- // The second step removes those elements from the element list and adds them to the subelement list
- // of the group object.
- // This two-step approach is necessary so that we're not removing elements as we go, which
- // would then throw off AEResolve() when it was trying to find objects by thier index value.
-
- if (error == noErr)
- {
- ElementReference memberElement;
- DocumentReference memberDocument;
- Rect bounds;
-
- for (index = 1; index <= numObjects; index++)
- {
- error = AEGetNthDesc(list, index, typeObjectSpecifier, &keyword, &ospec);
- if (error == noErr)
- {
- error = AEResolve(&ospec, kAEIDoMinimum, &token);
- }
-
- if (error == noErr)
- {
- error = GetDocumentReferenceFromToken(&token, &memberDocument);
- if (error != noErr)
- {
- goto CleanUp;
- }
- else if (document != memberDocument)
- {
- error = errAEEventNotHandled;
- goto CleanUp;
- }
-
- error = GetElementReferenceFromToken(&token, &memberElement);
- if (error != noErr)
- goto CleanUp;
-
- member[memberIndex] = memberElement;
- memberIndex++;
-
- AEDisposeDesc(&ospec);
- AEDisposeDesc(&token);
- }
- }
-
- for (index = 0; index < memberIndex; index++)
- {
- OrphanElement(member[index]);
- AdoptOrphan(GetElementSubElementList(group), member[index]);
- }
-
- bounds = CalculateElementBounds(group);
- SetElementBoundingBox(group, bounds);
- }
-
- CleanUp:
-
- AEDisposeDesc(&ospec);
- AEDisposeDesc(&token);
-
- return error;
- }
-
- #pragma mark -
- // -------------------------------------------------------------------------------------------
-
- static OSErr
- ProcessFormRelativePostition(const AEDesc* containerToken, const AEDesc *keyData, DescType desiredClass, ElementReference *element)
- {
- OSErr error = noErr;
-
- OSType positionEnum;
-
- ElementReference containerElement;
- ElementReference relativeElement;
-
- ElementType elementType;
- Boolean foundIt = false;
-
- *element = nil;
-
- error = GetElementReferenceFromToken(containerToken, &containerElement);
- if (error != noErr)
- goto CleanUp;
-
- ConvertObjectClassToElementType(desiredClass, &elementType);
-
- switch (keyData->descriptorType)
- {
- case typeEnumerated:
- if (DescToDescType((AEDesc*)keyData, &positionEnum) != noErr)
- {
- error = errAECoercionFail;
- goto CleanUp;
- }
-
- switch (positionEnum)
- {
- case kAENext:
- // get the next object of the desired type (ie, the one behind the container)
- relativeElement = GetPreviousElement(containerElement);
- foundIt = (relativeElement != nil && GetElementType(relativeElement) == elementType) ? true : false;
- while (relativeElement != nil && foundIt == false)
- {
- relativeElement = GetPreviousElement(relativeElement);
- foundIt = (relativeElement != nil && GetElementType(relativeElement) == elementType) ? true : false;
- }
-
- if (foundIt == false)
- error = errAENoSuchObject;
-
- break;
-
- case kAEPrevious:
- // get the previous object of the desired type (ie, the one in front of the container)
- relativeElement = GetNextElement(containerElement);
- foundIt = (relativeElement != nil && GetElementType(relativeElement) == elementType) ? true : false;
- while (relativeElement != nil && foundIt == false)
- {
- relativeElement = GetNextElement(relativeElement);
- foundIt = (relativeElement != nil && GetElementType(relativeElement) == elementType) ? true : false;
- }
-
- if (foundIt == false)
- error = errAENoSuchObject;
-
- break;
-
- default:
- error = errAEEventNotHandled;
- goto CleanUp;
- break;
- }
- break;
-
- default:
- error = errAECoercionFail;
- break;
- }
-
- CleanUp:
-
- if (foundIt)
- *element = relativeElement;
-
- return error;
- }
-
- #pragma mark -
- // -------------------------------------------------------------------------------------------
-
- Boolean CanGetProperty(DescType class, DescType property)
- {
- Boolean result;
-
- switch(property)
- {
- case pBestType:
- case pClass:
- case pDefaultType:
- case pObjectType:
-
- case pProperties:
- case pID:
-
- case pBounds:
- case pLocation:
- case pWidth:
- case pHeight:
-
- case pStrokeSize:
- case pStrokeColor:
-
- case pFillColor:
- result = true;
- break;
-
- // depends on class of object:
-
- case pContents:
- result = (class == cGroupedGraphic);
- break;
-
- case pPointList:
- result = (class == cPolygon);
- break;
-
- case pCornerCurveHeight:
- case pCornerCurveWidth:
- result = (class == cRoundedRectangle);
- break;
-
- case pStartPoint:
- case pEndPoint:
- result = (class == cGraphicLine);
- break;
-
- case pGraphicObjects:
- result = (class == cGroupedGraphic);
- break;
-
- default:
- result = false;
- break;
- }
-
- return result;
- }
-
- // -------------------------------------------------------------------------------------------
-
- Boolean CanSetProperty(DescType class, DescType property)
- {
- Boolean result;
-
- switch(property)
- {
- // can always be set:
-
- case pBounds:
- case pLocation:
- case pWidth:
- case pHeight:
-
- case pProperties:
-
- case pStrokeSize:
- case pStrokeColor:
-
- case pFillColor:
- result = true;
- break;
-
- // depends on class of object:
-
- case pPointList:
- result = (class == cPolygon);
- break;
-
- case pCornerCurveHeight:
- case pCornerCurveWidth:
- result = (class == cRoundedRectangle);
- break;
-
- case pEndPoint:
- case pStartPoint:
- result = (class == cGraphicLine);
- break;
-
- case pGraphicObjects:
- result = (class == cGroupedGraphic);
- break;
-
- // should be able to set, but not implemented yet:
-
- case pContents:
- result = false;
- break;
-
- // can never be set:
-
- default:
- result = false;
- break;
- }
-
- return result;
- }
-
- /*****************************************************************************
- *
- * CreatePolygonFromPoints
- *
- * Create a polygon element from a list of points
- *
- *****************************************************************************/
- PolyHandle CreatePolygonFromPoints(short numberOfPoints, Point *pointList)
- {
- Boolean polyClosed = false;
- PolyHandle polyHandle = OpenPoly();
- short pointIndex;
-
- if (polyHandle == nil)
- return polyHandle;
-
- // Move to the first point
-
- MoveTo(pointList[0].h, pointList[0].v);
-
- // Line to the rest of the points
-
- pointIndex = 1;
- while (pointIndex < numberOfPoints)
- {
- LineTo(pointList[pointIndex].h, pointList[pointIndex].v);
- pointIndex++;
- }
-
- // Make sure the polygon is a closed object
-
- if ((pointList[0].h != pointList[numberOfPoints-1].h) || (pointList[0].v != pointList[numberOfPoints-1].v))
- LineTo(pointList[0].h, pointList[0].v);
-
- ClosePoly();
-
- return polyHandle;
- }
-
- /*****************************************************************************
- *
- * CountPolygonPoints
- *
- * Returns the number of points owned by a polygon
- *
- *****************************************************************************/
- static short CountPolygonPoints(PolyHandle polygon)
- {
- return(((**polygon).polySize - sizeof(short) - sizeof(Rect)) / sizeof(Point));
- }
-
-
- /*****************************************************************************
- *
- * GetPolygonPoint
- *
- * Returns the specified point. Note that the index is one based, to get the
- * first point, pass 1.
- *
- *****************************************************************************/
-
- static Point GetPolygonPoint(PolyHandle polygon, short pointIndex)
- {
- Point pt;
- short numPts;
-
- pt.v = 0; // assume failure
- pt.h = 0;
-
- numPts = CountPolygonPoints(polygon); // found out how many are in the polygon
- if ((pointIndex >= 1) && (pointIndex <= numPts)) // sanity check
- pt = (**polygon).polyPoints[pointIndex - 1]; // extract the point
-
- return(pt); // return it to the caller
- }
-
-
-